﻿using System;
using System.IO;
using System.Threading;
using System.Collections.Generic;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Media;

namespace _2DEngine
{
    public class IEMusicManager
    {
        public class MusicTrack
        {
            public string SongName;
            public Song SongResource;

            public MusicTrack(string SongName, Song SongResource)
            {
                this.SongName = SongName;
                this.SongResource = SongResource;
            }

            public void Play(bool repeat)
            {
                if (repeat)
                    MediaPlayer.IsRepeating = true;

                if (MediaPlayer.State != MediaState.Stopped)
                    MediaPlayer.Stop();

                MediaPlayer.Play(SongResource);

                Engine.EventManager.TriggerEvent(
                "MUSIC_SERVICE",
                new MusicEventArgs(
                    "PLAY",
                    SongName,
                    Engine.Music.IndexOf(SongName),
                    repeat
                )
            );
            }
        }
        private List<MusicTrack> songs;

        public int Count
        {
            get { return songs.Count; }
        }

        public IEMusicManager(bool AutoLoadSongs)
        {
            songs = new List<MusicTrack>();

            if (AutoLoadSongs)
                LoadSongs();
        }

        public bool HasSong(string SongName)
        {
            if (songs.Count < 1)
                return false;

            foreach (MusicTrack music in songs)
                if (music.SongName == SongName)
                    return true;
            return false;
        }
        public int IndexOf(string SongName)
        {
            for (int i = 0; i < songs.Count; ++i)
                if (songs[i].SongName == SongName)
                    return i;

            // The Song Asset Does Not Exist!
            throw new Exception("Song Does Not Exists!");
        }

        public void AddSong(string SongName, Song SongResource)
        {
            if (HasSong(SongName))
                throw new Exception("A Song Already Exists With This Asset Name!");

            songs.Add(
                new MusicTrack(
                    SongName,
                    SongResource
                )
            );
        }
        public void RemoveSong(string SongName)
        {
            try
            {
                songs.RemoveAt(IndexOf(SongName));
            }
            catch { }
        }

        private void LoadSongs()
        {
            ThreadStart threadStarter = delegate
            {
                string Dir = Engine.Content.RootDirectory + @"\" + EngineSettings.Content.MusicFolder;
                DirectoryInfo info = new DirectoryInfo(Dir);
                foreach (FileInfo file in info.GetFiles("*.XNB"))
                {
                    string sSongName = file.Name.Substring(0, file.Name.Length - 4);
                    AddSong(
                        sSongName,
                        Engine.Content.Load<Song>(
                            string.Format(
                                @"{0}\{1}",
                                Dir,
                                sSongName
                            )
                        )
                    );
                }
            };
            Thread loadingThread = new Thread(threadStarter);
            loadingThread.Start();
        }

        public MusicTrack this[string SongName]
        {
            get
            {
                try { return songs[IndexOf(SongName)]; }
                catch { return null; }
            }
        }
        public MusicTrack this[int Index]
        {
            get
            {
                if (Index < songs.Count)
                    return songs[Index];
                return null;
            }
        }

        public void Stop()
        {
            MediaPlayer.Stop();
            Engine.EventManager.TriggerEvent(
                "MUSIC_SERVICE",
                new MusicEventArgs(
                    "STOP",
                    null,
                    -1,
                    false
                )
            );
        }
        public void Pause()
        {
            MediaPlayer.Pause();
            Engine.EventManager.TriggerEvent(
                "MUSIC_SERVICE",
                new MusicEventArgs(
                    "PAUSE",
                    null,
                    -1,
                    false
                )
            );
        }
        public void Resume()
        {
            MediaPlayer.Resume();
            Engine.EventManager.TriggerEvent(
                "MUSIC_SERVICE",
                new MusicEventArgs(
                    "RESUME",
                    MediaPlayer.Queue[0].Name,
                    Engine.Music.IndexOf(MediaPlayer.Queue[0].Name),
                    MediaPlayer.IsRepeating
                )
            );
        }

        public void Play(string SongName)
        {
            Play(SongName, false);
        }
        public void Play(string SongName, bool repeat)
        {
            MusicTrack track = this[SongName];

            if (track != null)
                Play(track.SongResource, repeat);
        }
        public void Play(Song song)
        {
            Play(song, false);
        }
        public void Play(Song song, bool repeat)
        {
            MediaPlayer.IsRepeating = repeat;
            MediaPlayer.Play(song);

            Engine.EventManager.TriggerEvent(
                "MUSIC_SERVICE",
                new MusicEventArgs(
                    "PLAY",
                    song.Name,
                    IndexOf(song.Name),
                    repeat
                )
            );
        }
    }

    public class MusicEventArgs : EventArgs
    {
        public string Action;
        public string SongName;
        public int SongIndex;
        public bool IsRepeating;

        public MusicEventArgs(string action, string songName, int songIndex, bool isRepeating)
        {
            this.Action = action;
            this.SongName = songName;
            this.SongIndex = songIndex;
            this.IsRepeating = isRepeating;
        }
   }
}